TypeScript 写一个事件管理器
编写一个单例的基类
因为一般 EventMananger 是全局管理器,所以这里做一个单例基类
export default class Singleton{
static getInstance<T extends {}>(this: new () => T): T {
if(!(<any>this).instance){
(<any>this).instance = new this();
}
return (<any>this).instance;
}
}
编写一个承载数据的事件基类
import { EventID } from './EventID'
import EventMananger from './EventManager'
/**
* 传输事件的基本单元,如果想要传输更多不一样的数据需要自己再实例一个对象
*/
export default class EventData<T> {
public eid: EventID
private _data: T | null
/**
* 这里使用 private 修饰,避免用户直接创建这个对象
* @param eid 当前事件的类型
*/
private constructor(eid: EventID) {
this.eid = eid
this._data = null;
}
public Send(arg: T): void {
this._data = arg;
EventMananger.getInstance().SendEvent(this)
}
public get data() {
return this._data;
}
public static CreateEvent<T>(eventId: EventID): EventData<T> {
return new EventData<T>(eventId)
}
}
编写一个观察者接口
import EventData from "./EventData";
/**
* 事件监听者基类
*/
export default interface IEventObserver {
HandleEvent<T>( resp: EventData<T>):void
}
编写管理器
导入集合工具类:
npm install typescript-collections --save
注意:要把 tsconfig 里面的这个改一下
"moduleResolution": "node"
下面是代码
import * as Collections from 'typescript-collections';
import Singleton from '../Singleton'
import EventData from './EventData'
import { EventID } from './EventID'
import IEventObserver from './IEventObserver'
export default class EventManager extends Singleton {
// 维护一个观察者队列
private observerList: Collections.Dictionary<EventID, Collections.LinkedList<IEventObserver>> =
new Collections.Dictionary<EventID,Collections.LinkedList<IEventObserver>>()
//private readonly eventQueue:Collections.Queue<EventData> = new Collections.Queue<EventData>(); //消息队列
/**
* 发送事件
* @type 事件类型
* @args 携带数据
*/
public SendEvent<T>(eve: EventData<T>) {
// 如果没有观察者监听这个事件则结束
if (!this.observerList.containsKey(eve.eid)) return
// 通知监听了这个事件的全部观察者
let observers = this.observerList.getValue(eve.eid)
observers?.forEach((x) => {
if (x != null) {
x.HandleEvent(eve)
}
})
}
/**
* 注册一个监听者
* @param newobj 需要注册的监听者
* @param eid 需要监听的事件 ID
*/
private RegisterObj(newobj: IEventObserver, eid: EventID): void {
if (!this.observerList.containsKey(eid)) {
let list = new Collections.LinkedList<IEventObserver>()
list.add(newobj)
this.observerList.setValue(eid, list)
} else {
let list = this.observerList.getValue(eid)
// 不存在才要添加
if (list != null && !list.contains(newobj)) {
list.add(newobj);
}
}
}
/**
* 监听者在这里注册,注意这里形参是可变参数
* @param newobj 需要被注册的监听者
* @param eids 需要监听的事件列表
* @returns
*/
public static Register(newobj: IEventObserver, ...eids: EventID[]): void {
for (const eid of eids) {
EventManager.getInstance().RegisterObj(newobj, eid)
}
}
/**
* 移除监听者
* @param removeObj 需要移除的监听对象
*/
public RemoveObj(removeObj: IEventObserver): void {
this.observerList.forEach((k, v) => {
let list = v
list.remove(removeObj)
})
}
/**
* 移除一个监听者
* @param removeObj 需要移除的对象
* @returns
*/
public static Remove(removeObj: IEventObserver): void {
console.log(`销毁了 ${removeObj}`);
EventManager.getInstance().RemoveObj(removeObj)
}
}
在 Vue3 中使用测试
import EventManager from '../ts/util/EventTools/EventManager'
import IEventObserver from '../ts/util/EventTools/IEventObserver'
import EventData from '../ts/util/EventTools/EventData'
import { EventID } from '../ts/util/EventTools/EventID'
class Test implements IEventObserver {
constructor() {
EventManager.Register(this, EventID.TEST)
}
HandleEvent<T>(resp: EventData<T>): void {
console.log('执行了')
console.log(resp)
}
}
let temp = new Test()
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
count: 0
}
},
setup() {
const INIT_OPTIONS = {
width: 640,
height: 480,
color: "#00FF00",
label: "VGA",
};
// 这里使用 typeof 快速匹配类型
let event = EventData.CreateEvent<typeof INIT_OPTIONS>(EventID.TEST)
return {
onclick: () => {
event.Send(INIT_OPTIONS)
}
}
},
// 要在生命周期结束时销毁,否则会导致内存泄漏(因为在 EventManager 中一直被引用着,没有释放)
beforeUnmount() {
EventManager.Remove(temp);
}
}